/*
 * Email Notify
 * Author: Antonio Nastasi
 * Email: sifcenter (at) gmail.it
 * Version: 0.1
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "plasma-emailnotify.h"
#include <QPainter>
#include <QFontMetrics>
#include <QSizeF> 
#include <QString>
#include <plasma/svg.h>
#include <plasma/theme.h>
#include <KStandardDirs>

 
EmailNotify::EmailNotify(QObject *parent, const QVariantList &args)
    : Plasma::Applet(parent, args),
    m_svg("", this),
    m_icon("emailnotify")
{   	   
    setHasConfigurationInterface(true);
    setDrawStandardBackground(true);
    resize(210, 210);    
}
 
void EmailNotify::socketEncrypted()
{           
    qDebug() << "MODE:" << socket.mode();    
    state = CONNECTED; 
}

void EmailNotify::socketConnected()
{   
    qDebug() << "MODE:" << socket.mode();
    if(ssl == 0)
	state = CONNECTED;
}


/* read data from socket */ 
void EmailNotify::getMessage()
{
    QByteArray buffer;
    buffer = socket.readAll();
    qDebug() << "BUFFER:"  << buffer;    
    if(buffer.contains("+OK")){
	switch(state){
	    case CONNECTED:
		qDebug() << "Protocol OK: welcome";		
		sendMessage(LOGIN);
		break;
	    case NO_CONNECTED:
		qDebug() << "Code error";
		break;
	    case VERIFY_USER:
		qDebug() << "Verify user: user accepted";
		sendMessage(PASSWORD);
		break;
	    case VERIFY_PASSWORD:
		qDebug() << "Verify password: password accepted";
		sendMessage(STAT);
		break;
	    case CMD_STAT:
		qDebug() << "Command Stat";
		QStringList emails = QString(buffer).split(" ");
		bool ok;
		if((currentEmails !=-1) && (emails.at(1).toInt(&ok,10) > currentEmails))
		    playSound();	   
		currentEmails = emails.at(1).toInt(&ok,10);
		text= "You have " +  emails.at(1) + " new messages";
		socket.close();
		state = NO_CONNECTED;
		update();
		break;
	}
    } else if (buffer.contains("-ERR")){
	switch(state){
	     case NO_CONNECTED:
		qDebug() << "Code error";
		break;
	    case CONNECTED:
	    case CMD_STAT:
		qDebug() << "Protocol Error";
		text = "Protocol issues";		
		break;		
	    case VERIFY_USER:
		qDebug() << "Verify user: user NOT accept";
		text = "Wrong user";
		break;
	    case VERIFY_PASSWORD:
		qDebug() << "Verify password: password NOT accepted";
		text = "Authentication failed";
		break;   
	}	
	socket.close();
	state = NO_CONNECTED;
	update();
    }	
}

/* send message */
void EmailNotify::sendMessage(CommandType type){
    QString buffer;    
    if (login.isEmpty()){
	text = "Configure me please!";
	socket.close();
	update();
	return;
    }
    switch(type){
	case LOGIN:	    
	    buffer = "USER "+ login + "\n";
	    state = VERIFY_USER;
	    break;
	case PASSWORD:
	    buffer = "PASS " + password + "\n";
	    state = VERIFY_PASSWORD;
	    break;
	case STAT:
	    buffer = "STAT\n";	    
	    state = CMD_STAT;	    
	    break;
	default:
	    break;
    }
    socket.write(buffer.toUtf8());
}
 
EmailNotify::~EmailNotify(){
    if (failedToLaunch()) {
	//qDebug() << "failed";
    } else {
	socket.close();
    }
}

/* configure dialog: login,password
 * interval,sound			*/
void EmailNotify::showConfigurationInterface()
{   
    configDialog.show();
}

void EmailNotify::playSound()
{    
    if(!sound_file.compare("(Nothing)") || sound_file.isEmpty())
	return;
    QString file(KGlobal::dirs()->locate("sound",sound_file));    
    if(file.isEmpty())
	return;    
    media->setCurrentSource(file);
    media->play();
}


void EmailNotify::checkConfig()
{
    bool ok;
    config->reparseConfiguration ();
    server = generalGroup->readEntry( "Server", QString() );
    port = generalGroup->readEntry( "Port", QString().toInt(&ok,10));    
    ssl = generalGroup->readEntry( "SSL", QString().toInt(&ok,10));   
    login = generalGroup->readEntry( "Login", QString() );
    password = QByteArray::fromBase64(generalGroup->readEntry( "Password", QString()).toUtf8());
    interval = (generalGroup->readEntry("Interval",QString())).toInt(&ok,10);
    sound_file = generalGroup->readEntry( "Sound", QString() );   
}

 
void EmailNotify::init(){
    m_svg.setContentType(Plasma::Svg::SingleImage);
    
    config = new KConfig("emailnotifyrc");
    generalGroup = new KConfigGroup(config,"General");
   
    currentEmails = -1;    
    media = Phonon::createPlayer(Phonon::MusicCategory);
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(connectAndCheck()));    
    connect(&socket, SIGNAL(encrypted()), this, SLOT(socketEncrypted()));
    connect(&socket, SIGNAL(connected()), this, SLOT(socketConnected()));
    connect(&socket, SIGNAL(readyRead()), this, SLOT(getMessage()));
    connect(&socket, SIGNAL(error(QAbstractSocket::SocketError )),this,SLOT(errorConnection(QAbstractSocket::SocketError )));
    text = "Email Notify";
    if (m_icon.isNull()) {
        setFailedToLaunch(true, "Loading error!");
    }
    state = NO_CONNECTED;
    timer->start(1000);  
} 

void EmailNotify::connectAndCheck()
{    
    if( state >= CONNECTED){	
	return;
    }
    socket.close();
    checkConfig();
    if(server.isEmpty() || port ==0){
	text = "Configure me please!";
	update();
	return;
    }
    /*TODO check if there is a better method
     the waitForConnected hang app! */
    QTimer::singleShot(6000, this, SLOT(checkIfConnected()));   
    if(ssl)
	    socket.connectToHostEncrypted(server,port);
	else
	    socket.connectToHost(server,port);
    
   /* if(socket.waitForConnected(1000)){  
	qDebug() << "wait for connection: TRUE";
    }
    else { 
	qDebug() << "wait for connection: FALSE";
	
	socket.close();
	text = "Connection Error";
	update();
    }*/
    if(interval !=0)
	timer->setInterval(interval*1000);
}

void EmailNotify::checkIfConnected()
{
    /* connection timeout function */   
    if(socket.state() != QAbstractSocket::ConnectingState)
	return;
    text = "Connection Error";
    update();
    state = NO_CONNECTED;
    socket.close();    
}
 
 void EmailNotify::errorConnection(QAbstractSocket::SocketError error)
 {
     qDebug() << "Error" << error;
     text = "Connection Error";
     update();
     state = NO_CONNECTED;
     socket.close();   
 }
 
void EmailNotify::paintInterface(QPainter *p,
        const QStyleOptionGraphicsItem *option, const QRect &contentsRect)
{
    p->setRenderHint(QPainter::SmoothPixmapTransform);
    p->setRenderHint(QPainter::Antialiasing);   
    m_svg.resize((int)contentsRect.width(), (int)contentsRect.height());
    m_svg.paint(p, (int)contentsRect.left(), (int)contentsRect.top());    
    p->drawPixmap(7, 0, m_icon.pixmap((int)contentsRect.width(),(int)contentsRect.width()-14));
    p->save();   
    p->setPen(Qt::white);
    p->drawText(contentsRect, Qt::AlignBottom | Qt::AlignHCenter, text);
    p->restore();
}
 
#include "plasma-emailnotify.moc"
